﻿/*

filipesilvestrim - An open-source ActionScript 3.0 repository of codes for Game Developers 

http://code.google.com/p/filipesilvestrim/

Copyright (c) 2009 Filipe Ghesla Silvestrim, All Rights Reserved.

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

*/

package com.filipesilvestrim.util.time
{
	import flash.utils.getTimer;
	import flash.utils.Timer;
	import flash.events.TimerEvent;
	
	/**
	* Class...
	* <p/>
	* Something to write about this class
	* <p/>
	* @example The following code sets the volume level for your sound:
	* <listing version="3.0">
	* 	var mySound:Sound = new Sound(); mySound.setVolume(VOL_HIGH); 
	* </listing>
	* @see Array#pop()
	* @see Array
	*/
	public class Stopwatch 
	{
		// ___________________________________________________________________ CONSTANTS
		
		// ___________________________________________________________________ CLASS PROPERTIES
		private var _lastClock		: Number;
		private var _elapsed		: Number;
		private var _auxNumber 		: Number;
		private var _laps			: Array;
		
		// ___________________________________________________________________ INSTANCE PROPERTIES
		private var _timer			: Timer;	
		public var callbackTick		: Function;
		// ___________________________________________________________________ GETTERS AND SETTERS
		//hours return Math.floor(getElapsedTime()/(3600000));
		//days return Math.floor(getElapsedTime()/(24*3600000));
		
		public function getMinute(lapNumber : int = -1) : Number
		{
			_auxNumber = int(((_laps[lapNumber] - _elapsed) * 0.001) / 60) % 60;
			return (_auxNumber ^ (_auxNumber >> 31)) - (_auxNumber >> 31);
		}
		public function getSecond(lapNumber : int = -1) : Number
		{
			_auxNumber =  int(((_laps[lapNumber] - _elapsed) * 0.001) % 60);
			return (_auxNumber ^ (_auxNumber >> 31)) - (_auxNumber >> 31);
		}
		public function getCentsecond(lapNumber : int = -1) : Number
		{
			_auxNumber =  int(((_laps[lapNumber] - _elapsed) * 0.1) % 100);
			return (_auxNumber ^ (_auxNumber >> 31)) - (_auxNumber >> 31);
		}
		public function getMilissecond(lapNumber : int = -1) : Number
		{
			_auxNumber =  (_laps[lapNumber] - _elapsed);
			return (_auxNumber ^ (_auxNumber >> 31)) - (_auxNumber >> 31);
		}
		
		// ___________________________________________________________________ CONSTRUCTOR
		public function Stopwatch (offset : int = 5)
		{
			_timer 			= new Timer(offset);
			_timer.addEventListener(TimerEvent.TIMER, eventTick);
			_timer.stop();
			init();
		}
		
		// ___________________________________________________________________ PUBLIC METHODS
		/**
		* This is the typical format of a simple multiline documentation comment
		* for the myMethod() method.
		*
		* <p>This is the second paragraph of the main description
		* of the <code>myMethod</code> method.
		* Notice that you do not use the paragraph tag in the
		* first paragraph of the description.</p>
		* 
		* @param param1 Describe param1 here.
		* @param param2 Describe param2 here.
		* 
		* @return A value of <code>true</code> means this; 
		* <code>false</code> means that.
		*
		* @see someOtherMethod
		*/
		public function start () : void
		{
			_lastClock = getTimer();
			_timer.start();
		}
		
		public function stop () : void
		{
			_timer.stop();
		}
		
		public function reset () : void
		{
			init();
			start();
		}
		
		public function addLap ( val : Number ) : void
		{
			_laps.push(val);
		}
		
		public function getLap ( id : Number ) : Number
		{
			return _laps[id];
		}
		
		public function changeLap ( id : Number,  val : Number ) : void
		{
			_laps[id] = val;
		}
		
		public function checkLap ( id : int ) : Boolean
		{
			return _laps[id] <= _elapsed;
		}
		// ___________________________________________________________________ PRIVATE METHODS
		private function init () : void
		{
			_elapsed 		= 0;
			_lastClock 		= 0;
			_timer.reset();
			
			_laps			= null;
			_laps			= new Array();
			_laps[ -1] 		= 0;
		}
		
		// ___________________________________________________________________ EVENTS
		private function eventTick(e:TimerEvent):void 
		{
			_elapsed = (getTimer() - _lastClock);
			callbackTick(_elapsed);
		}
		
	}
}

